Hellforge General Crackme III
by LazaRuS


Tutorial by Lucifer48 [Immortal Descendants]
(August 13th, 1999)



The crackme is coded in C++ builder, it's very similar as delphi (i asking myself which one is the worse ?). There are a lot of garbage in the code, but the algo is easy. A bpx hmemcpy allow us to enter in the code:
XXXX:004028ED  CALL 004273E4		;result: eax=length of name (we exit from here)
XXXX:004028F2  LEA  EAX,[EBP-01DC]
XXXX:004028F8  CALL 0044DE94
XXXX:004028FD  INC  EAX			;length of name +1
XXXX:004028FE  CMP  EDI,EAX		;edi is the index of the loop
XXXX:00402900  LEA  EAX,[EBP-01DC]
XXXX:00402906  SETL DL
XXXX:00402909  AND  EDX,01
XXXX:0040290C  PUSH EDX			;EDX=0 or EDX=1
...
XXXX:0040291A  POP  ECX
XXXX:0040291B  TEST ECX,ECX		;if ECX=0, it is the end of the loop
XXXX:0040291D  JNZ  0040285D		;back to the beginning of the loop
We are in the end of a loop. What is it doing ? In fact, it's very simple, it adds every ascii value of each char of the name:
XXXX:004028A6  MOV  EDX,[EBP-0234]	;index of loop
XXXX:004028AC  ADD  EDX,[EBP-01E0]	;add the address of the name
XXXX:00402AB2  DEC  EDX
XXXX:00402AB3  MOVSX ECX,BYTE PTR [EDX]	;read one char (from the name)
XXXX:00402AB6  ADD  [EBP-0230],ECX	;big add
Example: For my name (Lucifer48), i get:
4C + 75 + 63 + 69 + 66 + 65 + 72 + 34 + 38 = 336h
Just after the loop:
XXXX:00402923  IMUL EAX,[EBP-0230],000A2D77
XXXX:0040292D  MOV  [EBP-230],EAX	;save the result for the final comparison
We continue:
XXXX:004029A5  CMP  EDI,EAX		;length of the two serials
XXXX:004029A7  LEA  EAX,[EBP-01E8]	; edi: length of the first serial
XXXX:004029AD  SETZ DL			; eax: length of the second serial
XXXX:004029B0  AND  EDX,01
XXXX:004029B3  PUSH EDX
...
XXXX:004029D4  POP  ECX
XXXX:004029D5  TEST CL,CL
XXXX:004029D7  JZ   00402B9C		;jump = the two serials haven't got the same size
Then, to go forward, we have to enter two serial of same length. We arrive now at the serial's loop; here again, it is enornous, but what it is doing is easy:
XXXX:00402A41  MOV  EDX,[EBP-023C]	;index of loop (k)
XXXX:00402A47  XOR  EAX,EAX
XXXX:00402A49  ADD  EDX,[EBP-01F0]	;address of first serial
XXXX:00402A4F  DEC  EDX
XXXX:00402A50  MOV  CL,[EDX]		;read the k-th character of the serial
...
XXXX:00402A9A  MOV  EDX,[EBP-0240]	;index of loop (k)
XXXX:00402AA0  POP  EAX			;AL= k-th character of the serial1
XXXX:00402AA1  ADD  EDX,[EBP-01F4]	;address of second serial
XXXX:00402AA7  MOV  ECX,0000000A
XXXX:00402AAC  DEC  EDX
XXXX:00402AAD  XOR  AL,[EDX]		;xor with the k-th character of serial2
XXXX:00402AAF  MOVSX EAX,AL
XXXX:00402AB2  CDQ
XXXX:00402AB3  IDIV ECX
XXXX:00402AB5  MOVSX EDX,DL		;useless instruction
...
XXXX:00402B93  POP  ECX			;ecx=0 or ecx=1
XXXX:00402B94  TEST ECX,ECX
XXXX:00402B96  JNZ  004029F2		;if ecx=1 then the loop isn't finished
So, each result of mod will be kept and put together (with a proc similar as wfprintf). We arrive now at the final comparison:
XXXX:00402BBF  LEA  EDX,[EBP-0200]	;d *edx: result of the name (what we must find)
XXXX:00402BC5  LEA  EAX,[EBP-10]	;d *eax: code from  the xor/mod (serial)
XXXX:00402BC8  CALL 0044DE7C		;comparison
XXXX:00402BCD  PUSH EAX
...
XXXX:00402BE1  POP  ECX
XXXX:00402BE2  TEST CL,CL
XXXX:00402BE4  JZ   00402C14		;jmp = bad serials
This is the most simple registration (for me):
Name/ Lucifer48
Serial/ 548273178
Serial/ 000000000

or

Serial/ 548273179
Serial/ 000000001

...

Serial/ <=1;>:8>1
Serial/ 999999999

Taking numbers is the easiest way, because we don't care about the mod Ah result. Last one...

Name/ Lucifer48
Serial/ Lucifer48
Serial/ 15E516530

It is the end !

Greetings: All ID members (Volatility, Torn@do, ...), Eternal Bliss, ACiD BuRN, Duelist, LaZaRuS, people on #cracking4newbies, french crackers, and other crackme makers.



(c) Lucifer48. All rights reversed